package com.masonluo.mlonlinejudge.service.impl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.masonluo.mlonlinejudge.dao.*;
import com.masonluo.mlonlinejudge.entity.IoSample;
import com.masonluo.mlonlinejudge.entity.Tag;
import com.masonluo.mlonlinejudge.entity.TestPaper;
import com.masonluo.mlonlinejudge.exceptions.ResourceNotFoundException;
import com.masonluo.mlonlinejudge.model.bo.*;
import com.masonluo.mlonlinejudge.model.dto.*;
import com.masonluo.mlonlinejudge.model.param.UpdateTestPaperParam;
import com.masonluo.mlonlinejudge.service.TaskService;
import com.masonluo.mlonlinejudge.service.TestPaperService;
import org.apache.commons.lang.StringEscapeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 试卷表 服务实现类
 * </p>
 *
 * @author yangqi
 * @since 2021-10-28
 */
@Service
public class TestPaperServiceImpl extends ServiceImpl<TestPaperRepository, TestPaper> implements TestPaperService {
    @Autowired
    private TestPaperRepository testPaperRepository;

    @Autowired
    private SelProblemRepository selProblemRepository;

    @Autowired
    private ProblemRepository problemRepository;

    @Autowired
    private ProblemTagRepository problemTagRepository;

    @Autowired
    private IoSampleRepository ioSampleRepository;

    @Autowired
    private TaskRepository taskRepository;

    @Autowired
    private TaskService taskService;

    private static final int _1MB = 1024 * 1024;


    @Override
    public Integer updateTestPaper(UpdateTestPaperParam updateTestPaperParam){
        boolean titleUpdate = !Objects.isNull(updateTestPaperParam.getTitle());
        boolean scoreUpdate = !Objects.isNull(updateTestPaperParam.getScore());
        boolean descriptionUpdate = !Objects.isNull(updateTestPaperParam.getDescription());
        boolean problemUpdate = !Objects.isNull(updateTestPaperParam.getQuestionList());
        int updateSuccess=0;
        if(titleUpdate){
            updateSuccess=updateTitle(updateTestPaperParam);
        }
        if(scoreUpdate){
            updateSuccess=updateScore(updateTestPaperParam);
        }
        if (descriptionUpdate){
            updateSuccess=updateDescription(updateTestPaperParam);
        }
        if(problemUpdate){
            if(testPaperRepository.paperProblemExist(updateTestPaperParam.getId())<=0){
                List<UpdateTPaperProblemDto> updateProblemList = updateTestPaperParam.getQuestionList();
                for (UpdateTPaperProblemDto updateTPaperProblemDto : updateProblemList) {
                    updateSuccess = updateProblem(updateTestPaperParam.getId(), updateTPaperProblemDto);
                }
            }
            else if(deletePaperProblem(updateTestPaperParam.getId())>0){
                List<UpdateTPaperProblemDto> updateProblemList = updateTestPaperParam.getQuestionList();
                for (UpdateTPaperProblemDto updateTPaperProblemDto : updateProblemList) {
                    updateSuccess = updateProblem(updateTestPaperParam.getId(), updateTPaperProblemDto);
                }
            }else {
                throw new IllegalArgumentException("更新题目失败");
            }


        }
        if(updateSuccess>0){
            return updateSuccess;
        }
        throw new ResourceNotFoundException("试卷更新失败");

    }
    private Integer updateProblem(Integer paperId,UpdateTPaperProblemDto updateTPaperProblemDto){
        return testPaperRepository.updateProblem(paperId,updateTPaperProblemDto);
    }

    private Integer updateTitle(UpdateTestPaperParam updateTestPaperParam){
        return testPaperRepository.updateTitle(updateTestPaperParam);

    }
    private Integer updateScore(UpdateTestPaperParam updateTestPaperParam){
        return testPaperRepository.updateScore(updateTestPaperParam);
    }
    private Integer updateDescription(UpdateTestPaperParam updateTestPaperParam){
        return testPaperRepository.updateDescription(updateTestPaperParam);
    }

    @Override
    public Integer addTestPaper(TestPaperDto testPaperDto){
        return testPaperRepository.addTestPaper(testPaperDto);
    }
    @Override
    public Integer selectId(TestPaperDto testPaperDto){
        return testPaperRepository.selectId(testPaperDto);
    }
    @Override
    public boolean addTestSelProblem(Integer paperId,List<TestPaperSelProblem> selProblemList, Integer type){
        for (TestPaperSelProblem testPaperSelProblem : selProblemList) {
            if (type != 2) {
                if (selProblemRepository.selectByIdType(testPaperSelProblem.getId(), type) == 0) {
                    return false;
                }
            } else {
                if (problemRepository.countById(testPaperSelProblem.getId()) == 0) {
                    return false;
                }
            }
            testPaperRepository.addTestSelProblem(paperId, testPaperSelProblem, type);

        }
        return true;
    }

    @Override
    public List<TestPaperBo> pageTestPaper(Integer current,Integer limit){
        return testPaperRepository.pageTestPaper(current,limit);
    }

    @Override
    public Integer getTotal(){
        return testPaperRepository.getTotal();
    }

    @Override
    public Integer deletePaperProblem(Integer id){
        return testPaperRepository.deletePaperProblem(id);
    }

    @Override
    public  List<TestPaperBo> findPaperByName(String name,Integer current,Integer limit){
        return testPaperRepository.findPaperByName(name,current,limit);
    }

    @Override
    public Integer getTotalByName(String name){
        return testPaperRepository.getTotalByName(name);
    }
    @Override
    public Integer problemExist(Integer id,Integer type){
        return selProblemRepository.problemExist(id,type);
    }

    @Override
    public TestPaperDetailBo getTestPaperDetail(Integer id,Integer taskId){

        //判断考试是否过期
        if (taskId!=null && taskService.judgeTimeout(taskId)){
            throw new IllegalArgumentException("未在考试时间段，无法查看试卷");
        }

        Integer examId[] = testPaperRepository.findExamId(id);
        TestPaperBo paperDetail = testPaperRepository.findPaperDetail(id);
        List<SelProblemDetailDto> choicesProblem = new ArrayList<>();
        List<SelProblemDetailDto> trueOrFalse = new ArrayList<>();
        List<TestPaperSelProblemDetailDto> choicesProblemDetail = new ArrayList<>();
        List<TestPaperSelProblemDetailDto> trueOrFalseDetail = new ArrayList<>();
        if(problemExist(id,0)>0){
            choicesProblem = testPaperRepository.getSelProblemDetail(id,0);
        }
        JsonTurnBean(choicesProblem, choicesProblemDetail);
        if(problemExist(id,1)>0){
            trueOrFalse = testPaperRepository.getSelProblemDetail(id,1);//判断题信息
        }

        JsonTurnBean(trueOrFalse, trueOrFalseDetail);

        List<TestPaperProblemBo> programList = new ArrayList<>();//有完整信息的编程题列表

        if(problemExist(id,2)>0){
            List<ProblemDetailDto> programmingQuestions = testPaperRepository.getProgrammingQuestionsDetail(id);
            List<TestPaperTagBo> tagList = new ArrayList<>();
            List<IoSampleBo> ioSampleList = new ArrayList<>();
            //没有tag列表和iosample列表的编程题列表
            for (ProblemDetailDto programmingQuestion : programmingQuestions) {
                TestPaperProblemBo problemBo = new TestPaperProblemBo();
                System.out.println(programmingQuestion.getId());
                if (problemTagRepository.countByProblemId(programmingQuestion.getId()) != null) {
                    tagList = problemTagRepository.findTestPaperTagByProblemId(programmingQuestion.getId());
                }
                if (ioSampleRepository.countByProblemId(programmingQuestion.getId()) != null) {
                    ioSampleList = ioSampleRepository.findTestPaperIoSampleByProblemId(programmingQuestion.getId());
                }
                problemBo.setId(programmingQuestion.getId());
                problemBo.setUserId(programmingQuestion.getUserId());
                problemBo.setTitle(programmingQuestion.getTitle());
                problemBo.setDescription(programmingQuestion.getDescription());
                problemBo.setInputDescription(programmingQuestion.getInputDescription());
                problemBo.setOutputDescription(programmingQuestion.getOutputDescription());
                problemBo.setTimeLimit(programmingQuestion.getTimeLimit());
                problemBo.setMemoryLimit(programmingQuestion.getMemoryLimit()/_1MB);
                problemBo.setLevel(programmingQuestion.getLevel());
                problemBo.setHint(programmingQuestion.getHint());
                problemBo.setVisible(programmingQuestion.isVisible());
                problemBo.setTestCaseId(programmingQuestion.getTestCaseId());
                problemBo.setScore(programmingQuestion.getScore());


                problemBo.setTags(tagList);
                problemBo.setIoSamples(ioSampleList);

                programList.add(problemBo);
            }
        }

        TestPaperDetailBo bo = new TestPaperDetailBo();
        bo.setExamId(examId);
        bo.setTitle(paperDetail.getTitle());
        bo.setDesc(paperDetail.getDesc());
        bo.setScore(paperDetail.getScore());
        bo.setChoicesProblem(choicesProblemDetail);
        bo.setTrueOrFalse(trueOrFalseDetail);
        bo.setProgrammingQuestions(programList);
        return bo;

    }

    private void JsonTurnBean(List<SelProblemDetailDto> choicesProblem, List<TestPaperSelProblemDetailDto> choicesProblemDetail) {
        for(SelProblemDetailDto selProblemDetailDto : choicesProblem){
            TestPaperSelProblemDetailDto testPaperSelProblemDetailDto = new TestPaperSelProblemDetailDto();
            testPaperSelProblemDetailDto.setCorrect(selProblemDetailDto.getCorrect());
            testPaperSelProblemDetailDto.setType(selProblemDetailDto.getType());
            testPaperSelProblemDetailDto.setTitle(selProblemDetailDto.getTitle());
            testPaperSelProblemDetailDto.setId(selProblemDetailDto.getId());
            testPaperSelProblemDetailDto.setLevel(selProblemDetailDto.getLevel());
            testPaperSelProblemDetailDto.setScore(selProblemDetailDto.getScore());

            String answer = StringEscapeUtils.unescapeJava(selProblemDetailDto.getAnswer());
            JSONArray jsonArray = new JSONArray(answer);
            TestPaperSelProblemAnswerDto[] testPaperSelProblemAnswerDtos = new TestPaperSelProblemAnswerDto[jsonArray.size()];
            for (int i=0; i < jsonArray.size(); i++)    {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                String prefix = jsonObject.getStr("prefix");
                String content = jsonObject.getStr("content");
                TestPaperSelProblemAnswerDto t = new TestPaperSelProblemAnswerDto();
                t.setPrefix(prefix);
                t.setContent(content);
                testPaperSelProblemAnswerDtos[i] = t;
            }
            testPaperSelProblemDetailDto.setAnswers(testPaperSelProblemAnswerDtos);
            choicesProblemDetail.add(testPaperSelProblemDetailDto);
        }
    }
}
